from PySide2.QtWidgets import (QApplication, QMainWindow, 
                                QListView, QMenu, QInputDialog, QMessageBox, QLineEdit,
                                QStyledItemDelegate)
from PySide2.QtGui import QStandardItemModel, QStandardItem, QCursor, QPainter, QPalette
from PySide2.QtCore import Qt, QModelIndex, QRect, QSize
from adelegate import myDelegate


class myWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.listdata = ['Python', 'QT', 'PySide2', 'MVC', 'Item 5']

        # 创建列表视图和数据模型
        self.listview = QListView(self)                            # 列表视图
        self.model = QStandardItemModel()                          # 数据模型
        self.listview.setModel(self.model)                         # 设置视图和模型的关联

        # 将列表视图设为主窗口的中央部件，并设置主窗口标题
        self.setCentralWidget(self.listview)
        self.setWindowTitle('QListView-QStandardItemModel Example')

        # 设置列表视图
        # listview.setSelectionMode(QListView.ExtendedSelection)    # 允许多选
        self.listview.setSelectionMode(QListView.SingleSelection)   # 允许单选
        self.listview.setAlternatingRowColors(True)                 # 交替行颜色
        # self.listview.setEditTriggers(QListView.NoEditTriggers)   # 禁止编辑
        self.listview.setSpacing(10)                                # 设置行间距
        self.listview.setAutoScroll(True)                           # 自动滚动条

        # 设置自定义委托
        delegate = myDelegate(self.listview)
        self.listview.setItemDelegate(delegate)
        # 双击或选中后单击进入编辑状态
        self.listview.setEditTriggers(QListView.DoubleClicked | QListView.SelectedClicked)

        # 往数据模型中添加数据
        for x in self.listdata:
            item = QStandardItem(x)
            item.setCheckable(True)                                 # 设置为可选中,前有勾选框
            self.model.appendRow(item)
        
        # 启用上下文菜单
        self.listview.setContextMenuPolicy(Qt.CustomContextMenu)
        self.listview.customContextMenuRequested.connect(self.show_contextmenu)
    
    def show_contextmenu(self, pos):
        '''显示上下文菜单'''
        # 获取鼠标点击位置的索引
        index = self.listview.indexAt(pos)
        # 如果没有选中项，则创建一个上下文菜单，只允许添加数据
        if not index.isValid(): 
            contextmenu = QMenu(self)
            create = contextmenu.addAction('添加数据')
            create.triggered.connect(self.append_item)
        else:
            # 如果有选中项，则创建一个上下文菜单，允许对选中项进行操作
            contextmenu = QMenu(self)
            insert = contextmenu.addAction('插入')
            append = contextmenu.addAction('列表末尾追加') 
            up = contextmenu.addAction('上移')
            down = contextmenu.addAction('下移')
            delete = contextmenu.addAction('删除')
            clear = contextmenu.addAction('清空列表')
            # 连接菜单项的触发信号
            insert.triggered.connect(self.insert_item)
            append.triggered.connect(self.append_item)
            up.triggered.connect(self.up_item)
            down.triggered.connect(self.down_item)
            delete.triggered.connect(self.delete_item)
            clear.triggered.connect(self.clear_list)
        # 显示上下文菜单
        contextmenu.exec_(self.listview.mapToGlobal(pos))

    def insert_item(self):
        '''在选中项前插入数据'''
        index = self.listview.currentIndex()
        if not index.isValid(): return
        text, ok = QInputDialog.getText(self, '插入数据', '请输入要插入的数据:')
        if ok and text:
            item = QStandardItem(text)
            item.setCheckable(True)  # 设置为可选中,前有勾选框
            self.model.insertRow(index.row(), item)

    def append_item(self):
        '''在空列表添加数据，以及在列表末尾追加数据'''
        text, ok = QInputDialog.getText(self, '追加数据', '请输入要追加的数据:')
        if ok and text:
            item = QStandardItem(text)
            item.setCheckable(True)  # 设置为可选中,前有勾选框
            self.model.appendRow(item)

    def up_item(self):
        '''上移选中项'''
        index = self.listview.currentIndex()
        if not index.isValid() or index.row() == 0: return
        self.model.insertRow(index.row() - 1, self.model.takeRow(index.row())[0])

    def down_item(self):
        '''下移选中项'''
        index = self.listview.currentIndex()
        if not index.isValid() or index.row() == self.model.rowCount() - 1: return
        self.model.insertRow(index.row() + 1, self.model.takeRow(index.row())[0])

    def delete_item(self):
        '''删除选中项'''
        index = self.listview.currentIndex()
        if not index.isValid(): return
        row = index.row()             # 获取当前选中项的行号
        data = index.data()            # 获取当前选中项的数据
        reply = QMessageBox.question(self, '删除确认', f'确定要删除选中项吗？\n{data}', QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes: self.model.removeRow(index.row())
    
    def clear_list(self):
        '''清空列表'''
        reply = QMessageBox.question(self, '清空列表', '确定要清空列表吗？', QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes: self.model.clear()

        
if __name__ == '__main__':
    app = QApplication()
    window = myWindow()
    window.show()
    app.exec_()